原因

最近的一个项目,后台框架用的是React。本来以为直接看看项目代码就能照葫芦画瓢的,结果栽了一个跟头,在苦苦挣扎了一天后,
还是有很多地方看不懂,晚上冷静了一下,整理了一下看不懂的一些地方,做一下记录,很多时候都是因为TSX的语法不够熟练,导致看不懂,
有时间还是要重新学习一下语法,真正要彻底掌握ant design pro,需要前置学习的有es6,ts,react,jsx,dva,umi等。但是项目
时间的问题,彻底学习还是留待以后。其实在项目中实际运用可能会更快一些。下面是一些具体的问题

TypeScript泛型的问题

函数中的泛型

jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//定义学生的属性获取方法,一个返回字符串类型的name一个返回number类型的年龄
let itemFun = {
getName: (name: string): string=>{
return name;
},
getAge: (age: number):number=>{
return age;
}
}
//错误做法,这样的话value没有类型
let student1 = (value) => {
return value;
}
//相当于
let student1 = (value: any):any => {
return value;
}

//错误做法 会找不到T类型的类
let student3 = <T>(value: T): T => {
return value;
}
//规范做法
//解释:Value: T 表示声明参数是 T 类型的,后面的 : T 表示返回值也是 T 类型的。
let student3 = <T extends {}>(value: T): T => {
return value;
}

另外一种形式

jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 声明泛型类,类型变量为 T
class FilteredList<T> {
// 声明过滤器是以 T 为参数类型,返回 boolean 的函数表达式
filter: (v: T) => boolean;
// 声明数据是 T 数组类型
data: T[];
//构造器中 传入的filter是一个函数,T为参数,返回值为boolean
constructor(filter: (v: T) => boolean) {
this.filter = filter;
}

add(value: T) {
if (this.filter(value)) {
this.data.push(value);
}
}

get all(): T[] {
return this.data;
}
}

// 处理 string 类型的 FilteredList
const validStrings = new FilteredList<string>(s => !s);

// 处理 number 类型的 FilteredList
const positiveNumber = new FilteredList<number>(n => n > 0);

最常见一种形式的解释

jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
interface IProps {
color?: string;
size?: string;
}
interface IState {
aState: string;
bState: number;
}
export default class Animal extends Component<IProps, IState> {
constructor(props:IProps) {
super(props);
this.state = {
aState: '',
bState: 0
}
}
}

使用泛型进行 Props、 State 的类型定义。在这个两个泛型里面,前一个为Props,后一个为State。这样写的目的是在
定义后使用 this.state 和 this.props 时可以在编辑器中获得更好的智能提示,并且会对类型进行检查。

状态和属性

props 是组件对外的接口,state 是组件对内的接口。组件内可以引用其他组件,组件之间的引用形成了一个树状结构(组件树),如果下层组件需要使用上层组件的数据或方法,上层组件就可以通过下层组件的props属性进行传递,因此props是组件对外的接口。组件除了使用上层组件传递的数据外,自身也可能需要维护管理数据,这就是组件对内的接口state。根据对外接口props 和对内接口state,组件计算出对应界面的UI。

主要区别:

  • State是可变的,是一组用于反映组件UI变化的状态集合;state是私有的,可以认为state是组件的“私有属性(或者是局部属性)
  • 而Props对于使用它的组件来说,是只读的,要想修改Props,只能通过该组件的父组件修改。
    在组件状态上移的场景中,父组件正是通过子组件的Props, 传递给子组件其所需要的状态。

如何修改states

states有几个地方需要注意

  1. 用setState 修改State
  2. State 的更新是异步的
  3. State更新会被合并
  4. state类型是数组
  5. state类型是对象

    向子组件传递数据

    我们说 props 是组件对外的接口,state 是组件对内的接口。
    一个组件可以选择将 state(状态) 向下传递,作为其子组件的 props(属性):
    jsx
    1
    <MyComponent title={this.state.title}/>

自定义表单组件回传值

ant-design给我们提供了Form表单组件,但是如果想把其中的某些输入框转为组件,原有的表单取值和验证使用保持不变,该如何实现:
父组件:

jsx
1
2
3
4
5
6
7
8

<FormItem label="选项">
getFieldDecorator('option', {
initialValue: [defaultValue.option || '0', defaultValue.word]
})(
<OptionSelect/>
)}
</FormItem>

父组件使用getFieldDecorator最后可以取到option选项的值。
子组件:

jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
render() {
const {value} = this.props;
return(
<div>
<Select value={value[0]} onChange={this.selectChange}>
//...
</Select>
<Input value={value[1]} onChange={this.inputChange}/>
</div>
)
}
selectChange(val) {
const {onChange} = this.props;
//通知父组件更新
//封装数据传参
let changeVal;
//...
onChange(changeVal)
}
inputChange(e) {
const {onChange} = this.props;
}
OptionSelect.propTypes = {
value: PropTypes.array,
onChange: PropTypes.func
};

getFieldDecorator这个方法会向组件注入value参数,onChange方法。子组件通过value参数来初始化值,通过onChange方法通知父组件更新。